using UnityEngine;
using System.Collections;

[RequireComponent (typeof(BoxCollider))]
public class PlayerPhys : MonoBehaviour {

	public LayerMask collisionMask;

	private BoxCollider col;
	private Vector3 s;
	private Vector3 c;

	private Vector3 originalSize;
	private Vector3 originalCenter;
	private float colliderScale;

	private int collisionDivisionX = 3;
	private int collisionDivisionY = 10;

	private float skin = .005f;

	[HideInInspector]
	public bool grounded;

	[HideInInspector]
	public bool movementStopped;

	private Transform platform;
	private Vector3 platformPositionOld;
	private Vector3 deltaPlatformPos;

	Ray ray;
	RaycastHit hit;

	void Start(){
		col = GetComponent<BoxCollider>();
		colliderScale = transform.localScale.x;

		originalSize = col.size;
		originalCenter = col.center;
		SetCollider(originalSize, originalCenter);
	}

	public void Move (Vector2 moveAmount){

		float deltaY = moveAmount.y;
		float deltaX = moveAmount.x;
		Vector2 p = transform.position;

		if(platform)
		{
			deltaPlatformPos = platform.position - platformPositionOld;
		}
		else{
			deltaPlatformPos = Vector3.zero;
		}
		#region Vertical Collisions
		//Check collisions above and below
		grounded = false;

		for(int i=0; i<collisionDivisionX; i++)
		{
			float dir = Mathf.Sign(deltaY);
			float x = (p.x + c.x - s.x/2) + s.x/(collisionDivisionX-1) *i; //left, center and rightmost point of collider
			float y = p.y + c.y + s.y/2 * dir; //Bottom of collider
		
			ray = new Ray(new Vector2(x, y), new Vector2(0, dir));
			Debug.DrawRay(ray.origin, ray.direction);

			if(Physics.Raycast(ray, out hit, Mathf.Abs(deltaY)+ skin, collisionMask))
			{
				platform = hit.transform;
				platformPositionOld = platform.position;

				//get distance between player and ground
				float dst = Vector3.Distance(ray.origin, hit.point);
			
				if(dst>skin)
				{
					deltaY = -dst - skin * dir;
				}
				else {
					deltaY = 0;
				}
				grounded = true;
				break;
			}
			else
			{
				platform = null;
			}
		}
		#endregion

		#region Sideways Collisions
		//Check collisions left and right
		movementStopped = false;
		for(int i=0; i<collisionDivisionY; i++)
		{
			float dir = Mathf.Sign(deltaX);
			float x = p.x + c.x + s.x/2 * dir; //left, center and rightmost point of collider
			float y = p.y + c.y - s.y/2 + s.y/(collisionDivisionY-1) * i; //Bottom of collider
			
			ray = new Ray(new Vector2(x, y), new Vector2(dir, 0));
			Debug.DrawRay(ray.origin, ray.direction);
			
			if(Physics.Raycast(ray, out hit, Mathf.Abs(deltaX)+ skin, collisionMask))
			{
				//get distance between player and ground
				float dst = Vector3.Distance(ray.origin, hit.point);
				
				if(dst>skin)
				{
					deltaX = -dst - skin * dir;
				}
				else {
					deltaX = 0;
				}
				movementStopped = true;
				break;
				
			}
		}
		#endregion

		if(!grounded && !movementStopped)
		{
			Vector3 playerDir = new Vector3(deltaX, deltaY);
			Vector3 o = new Vector3(p.x + c.x + s.x/2 * Mathf.Sign(deltaX), p.y + c.y + s.y/2 * Mathf.Sign(deltaY));
			ray = new Ray(o, playerDir.normalized);
			
			if(Physics.Raycast(ray, Mathf.Sqrt(deltaX*deltaX + deltaY*deltaY), collisionMask))
			{
				grounded = true;
				deltaY = 0;
			}
		}
			

		Vector2 finalTransform = new Vector2(deltaX+deltaPlatformPos.x, deltaY);

		transform.Translate(finalTransform, Space.World);
	}

	public void SetCollider(Vector3 size, Vector3 center)
	{
		col.size = size;
		col.center = center;

		s = size * colliderScale;
		c = center * colliderScale;
	}
	
}
